package com.neusoft.neuiotms.sap;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.neusoft.bizcore.notice.notification.dto.NoticeDingDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordDTO;
import com.neusoft.bizcore.notice.notification.factory.DingdingMessageFactory;
import com.neusoft.bizcore.web.dto.result.ResultDTO;
import com.neusoft.bizcore.web.utils.JsonUtils;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class DingdingMessageFactoryImpl implements DingdingMessageFactory {

    private final static String DING_OPEN_API_BASE_URL = "https://oapi.dingtalk.com";
    private final static String DING_GET_TOKEN_URL = "/gettoken?appkey=%s&appsecret=%s";
    private final static String DING_CORPCONVERSATION_URL =
            "/topapi/message/corpconversation/asyncsend_v2?access_token=%s";

    private final static String AGENT_ID = "agentId";
    private final static String APP_KEY = "appKey";
    private final static String APP_SECRET = "appSecret";

    @Autowired
    private AuthMicroService authMicroService;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public void sendMessage(final NoticeRecordDTO msg) {
        final ResultDTO<Map<String, Object>> result = this.authMicroService.getDingDingConfig();
        final Map<String, Object> config = result.getData();

        final String agentId = (String) config.get(DingdingMessageFactoryImpl.AGENT_ID);
        final String appKey = (String) config.get(DingdingMessageFactoryImpl.APP_KEY);
        final String appSecret = (String) config.get(DingdingMessageFactoryImpl.APP_SECRET);

        final List<String> dingUserIdArray = Lists.newArrayList();
        for (final String systemUserId : msg.getDing().getUsers()) {
            final String dingUserId = this.authMicroService.exchangeDingUser(systemUserId).getData();
            if (StringUtils.isNotBlank(dingUserId)) {
                dingUserIdArray.add(dingUserId);
            }
        }

        if (dingUserIdArray.isEmpty()) {
            DingdingMessageFactoryImpl.log.warn("发送钉钉消息时，未查找到关联的钉钉用户");
            return;
        }

        final String accessToken = this.getDingAccessToken(appKey, appSecret);

        this.sendWorkNotice(msg.getDing(), accessToken, agentId, dingUserIdArray);

    }

    private String getDingAccessToken(final String appKey, final String appSecret) {
        final String jsonStr = this.restTemplate.getForObject(DingdingMessageFactoryImpl.DING_OPEN_API_BASE_URL
                + String.format(DingdingMessageFactoryImpl.DING_GET_TOKEN_URL, appKey, appSecret), String.class);

        DingdingMessageFactoryImpl.log.info("request for {}\n{}",
                String.format(DingdingMessageFactoryImpl.DING_GET_TOKEN_URL, appKey, appSecret),
                jsonStr);

        final Map<String, Object> result = JsonUtils.jsonToMap(jsonStr);
        return result.containsKey("access_token") ? (String) result.get("access_token") : null;
    }

    private void sendWorkNotice(final NoticeDingDTO dingDTO, final String accessToken, final String agentId,
            final List<String> users) {

        final Map<String, Object> typeJsonMap = new HashMap<>();
        typeJsonMap.put("msgtype", dingDTO.getMsgtype());
        typeJsonMap.put(dingDTO.getMsgtype(), JsonUtils.jsonToMap(dingDTO.getJsonBody()));

        final Map<String, Object> dingMsg = new HashMap<>();
        dingMsg.put("agent_id", agentId);
        dingMsg.put("msg", typeJsonMap);
        dingMsg.put("userid_list", users.stream().collect(Collectors.joining(",", "", "")));

        final ParameterizedTypeReference<Map<String, Object>> typeRef =
                new ParameterizedTypeReference<Map<String, Object>>() {
                };

        final HttpEntity<Map<String, Object>> request = new HttpEntity<>(dingMsg);

        final ResponseEntity<Map<String, Object>> response = this.restTemplate
                .exchange(DingdingMessageFactoryImpl.DING_OPEN_API_BASE_URL
                        + String.format(DingdingMessageFactoryImpl.DING_CORPCONVERSATION_URL, accessToken),
                        HttpMethod.POST,
                        request,
                        typeRef);

        final Map<String, Object> result = response.getBody();
        DingdingMessageFactoryImpl.log.info("response when send work notice to ding ding {} {}",
                JsonUtils.pojoToJson(typeJsonMap),
                JsonUtils.pojoToJson(result));
    }

}
